/**
 * @author Swiip
 * Describes the Standard Component Interface for a graphical with multiple view component
 * @class Archetype.component.multiViewComponent
 * @name Archetype.component.multiViewComponent
 * @extends Archetype.component.multiViewComponent
 */

Archetype.Component.create(["Archetype.component.graphicalComponent"],
/**
 * @scope Archetype.component.multiViewComponent.prototype
 */
{
    name: "Archetype.component.graphicalStateComponent",
    /**
     * @function
     * initialize views from configuration
     */
    beforeInstanciate: function(definition) {	
		if(typeof this.setup.views != "undefined") {
    		if(typeof this.setup.dependencies == "undefined") {
            	this.setup.dependencies = {};
            }
    		if(typeof this.setup.dependencies.html == "undefined") {
    			this.setup.dependencies.html = {};
	    		$A(this.setup.views).each(function(viewName) {
	    			//the two "(.*)" in the regexp are used to match the last match of component
	    			var viewNameWithUpperCase = viewName.substr(0, 1).toUpperCase() + viewName.substr(1);
	    			this.setup.dependencies.html[viewName] = this.name.replace(/(.*)component(.*)/, "$1template$2") + viewNameWithUpperCase;
	    		}.bind(this));
    		}
    		this.state = this.setup.views[0];
    		this.changeState = function(state) {
    			this.state = state;
    			this.render();
    		}
    	} else {
    		Logger.warn("You need to define setup.views in order to list avalaible views");
    	}
    },
	/**
	 * Renders the view as a String, must be implemented by the graphical component
	 * Takes no parameters.
	 *
	 * @return {String} the view as a string to insert in the DOM
	 */
	renderViewAsString:  function() {
        if($exist(this.templates) && $exist(this.templates[this.state]) ) {
        	return this.templates[this.state].evaluate(this);
        } else {
            Logger.warn("Please override 'renderViewAsString' or define a template named like the current state.");
        }
        return "";
	},
	/**
	 * Render the view. Uses renderViewAsString().
	 *
	 * @param {DOMNode} Element on which the Insertion will be applied
	 * @param {Insertion} [Insertion object] Usually prototype ones. Do not define to replace the element.
	 * @see http://www.prototypejs.org/api/insertion
	 *
	 * @exemple this.render(document.body, Insertion.Bottom);
	 */
	render: function(/*DOMNode*/element, /*Insertion*/insertionObject) {
    	if(typeof element == "undefined" && typeof this.anchor != "undefined") {
    		element = this.anchor;
    	}
    		
	    if(typeof insertionObject == "undefined") {
	    	$(element).update(this.renderViewAsString());
	    } else {
	    	new insertionObject(element, this.renderViewAsString());
	    }
	    
	    this.afterRender();
	    this._instanciateInnerComponents(element);
	},
	/**
	 * Called by default after a "render"<br>
	 * override this to set handlers after a typical render<br>
	 * By default, apply behaviors listeners 
	 * @function
	 */
	afterRender: function() {
		var that = this;
		
		if(this.anchor != null) {
			var anchor = $E(this.anchor);
		} else {
			var anchor = $E(document);
		}
		
		if(this.observe != null) {
			var observe = this.observe;
		} else {
			var observe = function(element, eventType, callback) {
				$E(element).observe(eventType, callback);
			}
		}
		
		if($H(this.setup.dependencies.html).size() >= 1 && typeof this.setup.dependencies.html[this.state] != "undefined") {
			$H(this.setup.behaviors[this.state]).each(function(behavior) {
				var selector = behavior.key;
				var callbacks = behavior.value;
				
				anchor.select(selector).each(function(element) {
					$H(callbacks).each(function(callback) {
						var eventType = callback.key;
						var eventCallback = callback.value;
						
						observe(element, eventType, eventCallback.bind(that));
					});
				});
			});
		}
	}
});